<?php
/**
 * Niushop商城系统 - 团队十年电商经验汇集巨献!
 * =========================================================
 * Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
 * ----------------------------------------------
 * 官方网址: https://www.niushop.com
 * =========================================================
 */

namespace addon\wechatpay\model;

use app\exception\ApiException;
use app\model\order\OrderMessage;
use app\model\system\Cron;
use app\model\BaseModel;
use addon\weapp\model\Config as WeappConfig;
use addon\wechat\model\Config as WechatConfig;
use app\model\system\Pay as PayModel;
use think\facade\Log;

/**
 * 微信支付配置
 * 版本 1.0.4
 */
class Pay extends BaseModel
{
    /**
     * 支付接口实例
     * @var
     */
    private $app;

    /**
     * 是否是小程序端
     * @var int
     */
    private $is_weapp = 0;

    /**
     * 支付配置
     * @var array|mixed
     */
    private $config = [];

    /**
     * 微信支付接口版本
     * @var string
     */
    private $api = 'v2';

    /**
     * 站点id
     * @var
     */
    private $site_id;

    public function __construct($is_weapp = 0, $site_id = 1)
    {
        $this->is_weapp = $is_weapp;
        $this->site_id = $site_id;

        // 支付配置
        $config_model = new Config();
        $this->config = $config_model->getPayConfig($site_id)[ 'data' ][ 'value' ];
        if (empty($this->config)) throw new ApiException(-1, "平台未配置微信支付");

        $this->api = $this->config[ 'api_type' ];
        $this->config[ 'site_id' ] = $site_id;

        if ($is_weapp == 0) {
            $wechat_config = ( new WechatConfig() )->getWechatConfig($this->site_id)[ 'data' ][ 'value' ];
            $this->config[ 'appid' ] = $wechat_config[ 'appid' ] ?? '';
        } else {
            $weapp_config = ( new WeappConfig() )->getWeappConfig($this->site_id)[ 'data' ][ 'value' ];
            $this->config[ 'appid' ] = $weapp_config[ 'appid' ] ?? '';
        }

        $this->factory();
    }

    /**
     * 实例化支付接口
     */
    public function factory()
    {
        $class = 'addon\\wechatpay\\model\\' . ucfirst($this->api);
        if (!class_exists($class)) throw new ApiException(-1, "Class '{$class}' not found");

        try {
            $this->app = new $class($this->config);
        } catch (\Exception $e) {
            Log::write('微信支付配置错误:' . $e->getMessage() . $e->getFile() . $e->getLine());
            throw new ApiException(-1, "微信支付配置错误");
        }
    }

    /**
     * 生成支付
     * @param $param
     */
    public function pay($param)
    {
        if (!$this->config[ 'pay_status' ]) return $this->error([], '平台未启用微信支付');

        ///绑定商户数据
        $pay_model = new PayModel();
        $pay_model->bindMchPay($param[ "out_trade_no" ], [ "app_id" => $this->config[ "appid" ] ]);

        if ($param[ 'trade_type' ] == 'JSAPI' || $param[ 'trade_type' ] == 'APPLET') {
            $member_info = model('member')->getInfo([ [ "member_id", "=", $param[ "member_id" ] ] ], 'weapp_openid,wx_openid');
            if (empty($member_info)) return $this->error(-1, '未获取到会员信息');
            $param[ 'openid' ] = $this->is_weapp ? $member_info[ 'weapp_openid' ] : $member_info[ 'wx_openid' ];
        }

        try {
            $result = $this->app->pay($param);
            return $result;
        } catch (\Exception $e) {
            Log::write('微信支付接口调用失败，请求参数：' . json_encode($param) . ' 错误原因：' . $e->getMessage() . $e->getFile() . $e->getLine());
            return $this->error([], '微信支付接口调用失败');
        }
    }

    /**
     * 支付异步通知
     * @param $param
     * @return mixed
     */
    public function payNotify()
    {
        return $this->app->payNotify();
    }

    /**
     * 关闭支付
     * @param $param
     */
    public function close($param)
    {
        try {
            return $this->app->payClose($param);
        } catch (\Exception $e) {
            Log::write('微信订单关闭失败，请求参数：' . json_encode($param) . ' 错误原因：' . $e->getMessage() . $e->getFile() . $e->getLine());
            return $this->error([], '微信订单关闭失败');
        }
    }

    /**
     * 微信原路退款
     * @param $param
     */
    public function refund($param)
    {
        if (!$this->config[ 'refund_status' ]) return $this->error([], '平台未启用微信退款');

        try {
            $mch_info = empty($param[ "pay_info" ][ 'mch_info' ]) ? [] : json_decode($param[ "pay_info" ][ 'mch_info' ], true);
            $this->config[ "appid" ] = $mch_info[ "app_id" ] ?? $this->config[ "appid" ];//替换为商户自己的appid
            $this->factory();

            return $this->app->refund($param);
        } catch (\Exception $e) {
            Log::write('微信退款失败，请求参数：' . json_encode($param) . ' 错误原因：' . $e->getMessage() . $e->getFile() . $e->getLine());
            return $this->error([], '微信退款失败');
        }
    }

    /**
     * 微信转账到零钱
     * @param array $param
     */
    public function transfer(array $param)
    {
        if (!$this->config[ 'transfer_status' ]) return $this->error([], '平台未启用微信转账');

        if ($this->api != $this->config[ 'transfer_type' ]) {
            $this->api = $this->config[ 'transfer_type' ];
            $this->factory();
        }

        try {
            $result = $this->app->transfer($param);
            return $result;
        } catch (\Exception $e) {
            Log::write('微信转账接口调用失败，错误原因：' . $e->getMessage() . $e->getFile() . $e->getLine());
            return $this->error([], '微信转账接口调用失败');
        }
    }


    /**
     * 微信转账到零钱新版本回调
     */
    public function transferNotify()
    {
        if (!$this->config[ 'transfer_status' ]) return $this->error([], '平台未启用微信转账');
        if ($this->api != $this->config[ 'transfer_type' ]) {
            $this->api = $this->config[ 'transfer_type' ];
            $this->factory();
        }
        try {
            return $this->app->transferNotify();
        } catch (\Exception $e) {
            Log::write('微信转账接口回调处理失败，错误原因：' . $e->getMessage() . $e->getFile() . $e->getLine());
            return $this->error([], '微信转账接口回调处理失败');
        }
    }


    /**
     * 撤销微信转账
     * @param $out_bill_no 商户单号
     * @return array
     */

    public function transferCancel($out_bill_no){

        if (!$this->config[ 'transfer_status' ]) return $this->error([], '平台未启用微信转账');
        if ($this->api != $this->config[ 'transfer_type' ]) {
            $this->api = $this->config[ 'transfer_type' ];
            $this->factory();
        }
        try {
            return $this->app->transferCancel($out_bill_no);
        } catch (\Exception $e) {
            Log::write('微信转账接口回调处理失败，错误原因：' . $e->getMessage() . $e->getFile() . $e->getLine());
            return $this->error([], '微信转账接口回调处理失败');
        }
    }
}